//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;

using OpenLS.Media;
using OpenLS.Spreadsheet.UI.Internals;

namespace OpenLS.Spreadsheet.UI
{
    using IncrementControl = Label;

    partial class RangeResources
    {
        public RangeResources()
        {
            InitializeComponent();
        }

        void selectionMouseDown(object sender, MouseButtonEventArgs e)
        {
            var selection = (FrameworkElement)sender;
            e.Handled = true;
            selection.CaptureMouse();
            DragDropManager.SetIsDown(selection, true);
            DragDropManager.SetStartPoint(selection, e.GetPosition(selection));
        }
        void selectionMouseUp(object sender, MouseButtonEventArgs e)
        {
            DragDropManager.DragSourceElement = null;
            DragDropManager.SetIsDown((DependencyObject) sender, false);
            Mouse.Capture(null);
        }
        void selectionMouseMove(object sender, MouseEventArgs e)
        {
            var outline = (FrameworkElement)sender;
            if (DragDropManager.GetIsDown(outline))
            {
                Point startPoint = DragDropManager.GetStartPoint((DependencyObject)sender);
                if (((Math.Abs(e.GetPosition(outline).X - startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) ||
                    (Math.Abs(e.GetPosition(outline).Y - startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
                {
                    DragStarted(sender, outline, e);
                }
            }
        }
        private void DragStarted(object sender, DependencyObject outline, MouseEventArgs e)
        {
            var rect = (FrameworkElement) sender;
            var selection = (Range) rect.DataContext;
            var cp = (ContentPresenter) rect.TemplatedParent;
            var cc = (ContentControl) cp.TemplatedParent;
            var grid = (WorksheetGrid) cc.Parent;
            Worksheet Worksheet = selection.Worksheet;
            DragDropManager.StartDrag(grid);
            DragDropManager.SetIsDown(outline, false);
            object data = DataObjectFactory.CreateDataObject(DragDropFormats.SpreadsheetSelection,
                                                             Worksheet.Selection.Label);
            //\\ClipboardManager.SetSelectionAddress(selection.Label);
//\\            data.SetData(DragDropFormats.SpreadsheetSelection, Worksheet.Selection.Label);
            Point mousePosition = e.GetPosition(grid);
            CellAddress a = grid.GetCellAddressAt(mousePosition);
            if (selection == null)
                return;
            CellRelativeAddress aa;
            if (selection is CellsRange)
            {
                var cellsRange = (CellsRange) selection;
                aa = a - cellsRange.TopLeftCell.Address;

                if (aa.Row == -1)
                    aa = new CellRelativeAddress(0, aa.Column);
                if (aa.Column == -1)
                    aa = new CellRelativeAddress(aa.Row, 0);
                if (aa.Row >= cellsRange.RowSpan)
                    aa = new CellRelativeAddress(cellsRange.RowSpan - 1, aa.Column);
                if (aa.Column >= cellsRange.ColumnSpan)
                    aa = new CellRelativeAddress(aa.Row, cellsRange.ColumnSpan - 1);
                DragDropManager.SetDragOffset(grid, aa);
            }
            else if (selection is FullRowRange)
            {
                aa = new CellRelativeAddress(a.Row - ((FullRowRange) selection).FirstRow.Index, 0);
                if (aa.Row >= 0)
                    aa = new CellRelativeAddress(aa.Row - 1, 0);
                DragDropManager.SetDragOffset(grid, aa);
            }
            else if (selection is FullColumnRange)
            {
                aa = new CellRelativeAddress(0, a.Column - ((FullColumnRange) selection).FirstColumn.Index);
                if (aa.Column >= 0)
                    aa = new CellRelativeAddress(0, aa.Column - 1);
                DragDropManager.SetDragOffset(grid, aa);
            }
            else
            {
                DragDropManager.SetDragOffset(grid, null);
            }
            DragDropManager.DoDragDrop(grid, data, DragDropEffects.Copy | DragDropEffects.Move);
        }

        static T GetAncestor<T>(DependencyObject obj) where T : DependencyObject
        {
            if (obj is T)
                return (T)(object)obj;
            return GetAncestor<T>(VisualTreeHelper.GetParent(obj));
        }


        void OnFillHandleQueryCursor(object sender, QueryCursorEventArgs args)
        {
            args.Cursor = (Keyboard.Modifiers & ModifierKeys.Control) != 0 ? OfficeCursors.FillIncrement : OfficeCursors.Fill;
            args.Handled = true;
        }

        void OnFillHandleMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var r = (IncrementControl)sender;
            if (e.LeftButton != MouseButtonState.Pressed)
                return;
            e.Handled = true;
            var cellsRange = (CellsRange) r.DataContext;
            Cell cell = cellsRange.FirstCell;
            CellsRange rr = cellsRange.Worksheet.GetAutoIncrementRange(cell);
            if (rr == null)
                return;
            SpreadsheetElement.SetAutoFillFor(sender, new AutoFill(cellsRange, sender as UIElement));
            DependencyObject editorRoot = EditionElement.GetEditorRoot((DependencyObject)sender);
            AutoFill autoFill = SpreadsheetElement.GetAutoFillFor(sender);
            autoFill.SetTarget(NavigationDirection.Down, rr.RowSpan - 1);
            autoFill.Apply();
            SpreadsheetElement.SetHighlight(editorRoot, null);
            SpreadsheetElement.SetAutoFill(editorRoot, null);
        }
        void OnFillHandleMouseDown(object sender, MouseButtonEventArgs e)
        {
            var r = (IncrementControl)sender;
            if (e.LeftButton != MouseButtonState.Pressed && e.RightButton != MouseButtonState.Pressed)
                return;
            e.Handled = true;
            var s = (Range)r.DataContext;
            if (s == null)
                return;
            if (s.Worksheet.Selection == null)
                return;
            if (!(s.Worksheet.Selection is CellsRange))
            return;
            var cr = (CellsRange)s.Worksheet.Selection;
            SpreadsheetElement.SetAutoFillFor(sender, new AutoFill(cr, sender as UIElement));
            Mouse.Capture(r);
        }
        void OnFillHandleMouseUp(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            var r = (IncrementControl)sender;
            var s = (Range)r.DataContext;
            if (s == null)
                return;
            object root = EditionElement.GetEditorRoot(r);
            AutoFill autoFill = SpreadsheetElement.GetAutoFillFor(sender);
            if (autoFill != null)
            {
                autoFill.UseIncrement = autoFill.HasNaturalIncrement;
                if ((Keyboard.Modifiers & ModifierKeys.Control) != 0)
                    autoFill.UseIncrement = !autoFill.UseIncrement;
                autoFill.Apply();
            }
            SpreadsheetElement.ForgetHightlightForAndClipboardMonitor(root);
            SpreadsheetElement.SetAutoFillFor(root, null);
            r.ReleaseMouseCapture();
        }
        void OnFillHandleMouseMove(object sender, MouseEventArgs e)
        {
            var rect = (IncrementControl)sender;
            var range = (Range)rect.DataContext;
            if (Mouse.Captured != rect)
                return;
            var worksheetGrid = GetAncestor<WorksheetGrid>(rect);
            worksheetGrid = worksheetGrid.GetHitGrid(e.GetPosition);
            Point pt = e.GetPosition(worksheetGrid);
            const double f = 10;
            if (pt.X < 0)
                pt.X -= Math.Pow(pt.X, 2) / f;
            if (pt.Y < 0)
                pt.Y -= Math.Pow(pt.Y, 2) / f;
            if (pt.X > worksheetGrid.ActualWidth)
                pt.X += Math.Pow(worksheetGrid.ActualWidth - pt.X, 2) / f;
            if (pt.Y > worksheetGrid.ActualHeight)
                pt.Y += Math.Pow(worksheetGrid.ActualHeight - pt.Y, 2) / f;
            WorksheetPane p = SpreadsheetElement.GetWorksheetPane(worksheetGrid);
            CellAddress ca = p.GetCellClosestAddressAt(pt);
            AutoFill autoFill = SpreadsheetElement.GetAutoFillFor(sender);
            int downLength = ca.Row - autoFill.Source.Address.BottomRight.Row - 1;
            int upLength = autoFill.Source.Address.TopLeft.Row - ca.Row;
            int rightLength = ca.Column - autoFill.Source.Address.BottomRight.Column - 1;
            int leftLength = autoFill.Source.Address.TopLeft.Column - ca.Column;
            int max = Math.Max(rightLength, Math.Max(leftLength, Math.Max(downLength, upLength)));
            p.EnsureVisible(ca);
            if (max <= 0)
            {
                autoFill.IsEnabled = false;
                return;
            }
            if (max == rightLength)
            {
                autoFill.SetTarget(NavigationDirection.Right, rightLength);
                return;
            }
            if (max == leftLength)
            {
                autoFill.SetTarget(NavigationDirection.Left, leftLength);
                return;
            }
            if (max == downLength)
            {
                autoFill.SetTarget(NavigationDirection.Down, downLength);
                return;
            }
            if (max == upLength)
            {
                autoFill.SetTarget(NavigationDirection.Up, upLength);
                return;
            }
        }
        void OnFillHandleKey(object sender, KeyEventArgs keyEventArgs)
        {
            Mouse.UpdateCursor();
        }
        void OnFillLoaded(object sender, MouseEventArgs mouseEventArgs)
        {
            var frameworkElement = (FrameworkElement)sender;
            var timer = new DispatcherTimer(DispatcherPriority.ApplicationIdle, frameworkElement.Dispatcher)
                            {Interval = TimeSpan.FromMilliseconds(200)};
            timer.Tick += delegate
            {
                Mouse.UpdateCursor();
                return;
            };
            frameworkElement.Tag = timer;
            timer.Start();
        }
        void OnFillUnloaded(object sender, MouseEventArgs mouseEventArgs)
        {
            var timer = (DispatcherTimer) ((FrameworkElement)sender).Tag;
            timer.Stop();
        }


    }
}
